using System;
using System.Collections.Generic;
using System.Text;
using System.Web.Compilation;
using System.Globalization;
using System.Collections.Specialized;
using System.Diagnostics;
using System.Web;
using System.Web.Caching;
using System.IO;

namespace Medianamik.Globalization
{
    public class TranslationResourceProvider : DisposableBaseType, IResourceProvider
    {
        #region Members
        String classKey;
        TranslationResourcesDAL dal;
        Dictionary<string, Dictionary<string, string>> resourceCache = new Dictionary<string, Dictionary<string, string>>();
        #endregion

        #region .ctor
        public TranslationResourceProvider(string classKey)
        {
            Debug.WriteLine(String.Format(CultureInfo.InvariantCulture, "TranslationResourceProvider.TranslationResourceProvider({0}", classKey));

            this.classKey = classKey;
            this.dal = new TranslationResourcesDAL(classKey);

            //if(HttpContext.Current != null)
                this.CreateCache();
        }
        #endregion

        #region IResourceProvider Members

        public object GetObject(string resourceKey, System.Globalization.CultureInfo culture)
        {
            if (HttpContext.Current != null)
            {
                Debug.WriteLine(String.Format(CultureInfo.InvariantCulture, "TranslationResourceProvider.GetObject({0}, {1}) - type:{2}", resourceKey, culture, this.classKey));

                if (Disposed)
                {
                    throw new ObjectDisposedException("TranslationResourceProvider object is already disposed.");
                }

                if (string.IsNullOrEmpty(resourceKey))
                {
                    throw new ArgumentNullException("resourceKey");
                }

                if (culture == null)
                {
                    culture = CultureInfo.CurrentUICulture;
                }

                string resourceValue = null;
                Dictionary<string, string> resCacheByCulture = null;
                // check the cache first
                // find the dictionary for this culture
                // check for the inner dictionary entry for this key
                if (resourceCache.ContainsKey(culture.Name))
                {
                    resCacheByCulture = resourceCache[culture.Name];
                    if (resCacheByCulture.ContainsKey(resourceKey))
                    {
                        resourceValue = resCacheByCulture[resourceKey];
                    }
                }

                // if not in the cache, go to the database
                if (resourceValue == null)
                {
                    // add this result to the cache
                    // find the dictionary for this culture
                    // add this key/value pair to the inner dictionary
                    lock (this)
                    {
                        if (resourceValue == null)
                        {
                            resourceValue = dal.GetResourceByCultureAndKey(culture, resourceKey);

                            if (resCacheByCulture == null)
                            {
                                resCacheByCulture = new Dictionary<string, string>();
                                if(!resourceCache.ContainsKey(culture.Name))
                                    resourceCache.Add(culture.Name, resCacheByCulture);
                            }
                            resCacheByCulture.Add(resourceKey, resourceValue);
                        }
                    }
                }
                return resourceValue;
            }
            else
            {
                return String.Empty;
            }
        }

        public System.Resources.IResourceReader ResourceReader
        {
            get
            {
                Debug.WriteLine(String.Format(CultureInfo.InvariantCulture, "TranslationResourceProvider.get_ResourceReader - type:{0}", this.classKey));

                if (Disposed)
                {
                    throw new ObjectDisposedException("TranslationResourceProvider object is already disposed.");
                }

                // this is required for implicit resources 
                // this is also used for the expression editor sheet 

                ListDictionary resourceDictionary = this.dal.GetResourcesByCulture(CultureInfo.InvariantCulture);

                return new TranslationResourceReader(resourceDictionary);
            }
        }

        #endregion


        #region Cache
        protected void CreateCache()
        {
			string path = GetCacheFile(classKey);

            CacheDependency dependency = new CacheDependency(path);

            HttpRuntime.Cache.Insert("TRANSLATIONS_" + classKey, resourceCache, dependency, Cache.NoAbsoluteExpiration, Cache.NoSlidingExpiration, CacheItemPriority.High, this.CacheRemoved);
        }

        protected void CacheRemoved(String cacheKey, Object o, CacheItemRemovedReason reason)
        {
            this.resourceCache.Clear();
            this.CreateCache();
        }
        #endregion

        protected override void Cleanup()
        {
            try
            {
                this.dal.Dispose();
                this.resourceCache.Clear();
            }
            finally
            {
                base.Cleanup();
            }
        }

		internal static string GetCacheFile(string pClassKey)
		{
			String basePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory,"CacheFiles\\Translations\\");

			if (!Directory.Exists(basePath))
				Directory.CreateDirectory(basePath);

			String filePath = Path.Combine(basePath, pClassKey + ".txt");
			if (!File.Exists(filePath))
				File.Create(filePath);

			return filePath;
		}
    }
}
